package testcase.card;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.NoSuchElementException;

import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.junit.Test;

import satir.card.Choice;

import satir.card.EventCard;

import satir.card.Question;
import satir.command.AskQuestionCmd;

import satir.player.Player;

import junit.framework.TestCase;

import junitx.util.PrivateAccessor;

public class EventCard_rubbish extends TestCase {

	/**
	 * Stub of AskQuestionCmdStub
	 * 
	 * @author Torrey Tsui
	 */
	public static class AskQuestionCmdStub extends AskQuestionCmd {
		public AskQuestionCmdStub(Question question, Player player) {
			super(question, player);
		}

		@Override
		public void execute() {
			System.out
					.println("Mother notices her children talk with classmate at night about 30 mins or more. As Father, what is your decision?\n"
							+ "1. Blame him/her and prohibit use the phone more than 5 mins.\n"
							+ "2. Talk with son/daughter and find the reason.\n"
							+ "3. Threaten son/daughter. If the situation still not change, you will modify the amount of pocket money.\n"
							+ "4. Ignore him/her.\n"
							+ "Your Answer?\n"
							+ "1 Awarded!!\n");
		}
	}

	// Forcing use magic tool card
	class EventCardStub extends EventCard {

		private boolean useMagicTool;

		public EventCardStub(String key, String name,
				ArrayList<Question> questions) {
			super(key, name, questions);
			useMagicTool = false;
		}

		/**
		 * Stub's method for setting test run parameters
		 * 
		 * @param useMagicTool
		 */
		public void setUseMagicTool(boolean useMagicTool) {
			this.useMagicTool = useMagicTool;
		}

		/**
		 * Override the useMagicTool card method that forcing the execution for
		 * test
		 */
		@Override
		protected boolean useMagicTool(Player player, String cardType) {
			return useMagicTool;
		}

		/**
		 * Force execute the doActivateCard method which is a protected method
		 * 
		 * @param player
		 */
		public void runDoActivate(Player player) {
			this.doActivateCard(player);
		}

	}

	private EventCardStub eventCard;
	private Player player;

	/**
	 * Sets up the test fixture. Called before every test case method.
	 */
	public void setUp() {

		// give choice
		ArrayList<Choice> choices;
		choices = new ArrayList<Choice>();
		choices.add(new Choice(
				"Blame him/her and prohibit use the phone more than 5 mins.",
				1, new Hashtable<String, Integer>()));
		choices.add(new Choice("Talk with son/daughter and find the reason.",
				1, new Hashtable<String, Integer>()));
		choices.add(new Choice(
				"Threaten son/daughter. If the situation still not change, you will modify the amount of pocket money.",
				-1, new Hashtable<String, Integer>()));
		choices.add(new Choice("Ignore him/her.", -1,
				new Hashtable<String, Integer>()));

		// give a question
		String question1 = "Mother notices her children talk with classmate at night about 30 mins or more. As Father, what is your decision?";
		player = new Player();
		Question question = new Question(question1, choices);

		// create questions array
		ArrayList<Question> questions = new ArrayList<Question>();
		questions.add(question);

		eventCard = new EventCardStub("card1", "Card 1", questions);

	}

	/**
	 * Tears down the test fixture. Called after every test case method.
	 */
	public void tearDown() {
	}

	/**
	 * Step number : 1 Goal : Question asked without choices and use magic tool
	 * , so no need to answer, no AskQuestionCmd has not been recorded , the
	 * player's self-esteem has not been added
	 */
	@Test
	public void testdoActivateCard_1() {

		// Force use magic tool card
		eventCard.setUseMagicTool(true);

		// system out
		final ByteArrayOutputStream systemOut = new ByteArrayOutputStream();
		PrintStream original = System.out;
		System.setOut(new PrintStream(systemOut)); // Start store the output
		String input = "1\n1"; // Indicate use magic tool card
		System.setIn(new ByteArrayInputStream(input.getBytes()));
		try {
			eventCard.runDoActivate(player); // Run the method to be tested
		} catch (NoSuchElementException e) {
		}



		eventCard.getKey();
		eventCard.getClassType();
	//	eventCard.getAction();
//		eventCard.getPlayer();
		assertEquals(true, true);
	}


	@Aspect
	public static class TestAspects {

		/**
		 * Define a Pointcut for monitoring a specific 'method call' inside a
		 * specific 'scope'
		 * 
		 * Method Call: the constructor of 'satir.card.Question' JavaCode:
		 * Question() AspectJCode: call(satir.card.Question.new(..))
		 * 
		 * Scope: inside the method call of 'EventCard_doActivateCard_1_1'
		 * JavaCode: EventCard_doActivateCard_1_1() AspectJCode:
		 * within(EventCard_doActivateCard_1_1)
		 * 
		 * Explanation: This Pointcut defined that it will be triggered when the
		 * constructor of 'satir.card.Question' called inside the class of
		 * 'EventCard_doActivateCard_1_1'
		 */
		@Pointcut("call(satir.command.AskQuestionCmd.new(satir.card.Question, satir.player.Player)) && args(q, p) && within(EventCard_doActivateCard_1_1)")
		public void interceptAskQuestionCmdConstructor(Question q, Player p) {
		}

		/**
		 * Define the follow-up action after the Pointcut of
		 * 'interceptAskQuestionCmdConstructor()' has been triggered
		 * 
		 * @return AskQuestionCmd
		 * 
		 *         Explanation: After 'interceptAskQuestionCmdConstructor()' has
		 *         been triggered , the new instance of AskQuestionCmd will be
		 *         replaced by creating and returning an instance of
		 *         AskQuestionCmdStub
		 */
		@Around("interceptAskQuestionCmdConstructor(q, p)")
		public AskQuestionCmd interceptConstructorForAskQuestionCmd(Question q,
				Player p) {
			return new AskQuestionCmdStub(q, p);
		}
	}
}
